<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow: flow::async::Concurrent_task_loop Class Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="namespaceflow.html">flow</a></li><li class="navelem"><a class="el" href="namespaceflow_1_1async.html">async</a></li><li class="navelem"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html">Concurrent_task_loop</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="summary">
<a href="#pub-types">Public Types</a> &#124;
<a href="#pub-methods">Public Member Functions</a> &#124;
<a href="#related">Related Functions</a> &#124;
<a href="classflow_1_1async_1_1Concurrent__task__loop-members.html">List of all members</a>  </div>
  <div class="headertitle"><div class="title">flow::async::Concurrent_task_loop Class Reference<span class="mlabels"><span class="mlabel">abstract</span></span></div></div>
</div><!--header-->
<div class="contents">

<p>The core <a class="el" href="namespaceflow_1_1async.html" title="Flow module containing tools enabling multi-threaded event loops operating under the asynchronous-tas...">flow::async</a> interface, providing an optionally multi-threaded thread pool onto which runnable <code>Task</code>s, optionally arranged into concurrency-avoiding <code>Op</code>s, can be boost.asio-posted for subsequent execution.  
 <a href="classflow_1_1async_1_1Concurrent__task__loop.html#details">More...</a></p>

<p><code>#include &lt;<a class="el" href="concurrent__task__loop_8hpp_source.html">concurrent_task_loop.hpp</a>&gt;</code></p>
<div class="dynheader">
Inheritance diagram for flow::async::Concurrent_task_loop:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1async_1_1Concurrent__task__loop__inherit__graph.svg" width="775" height="348"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<div class="dynheader">
Collaboration diagram for flow::async::Concurrent_task_loop:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1async_1_1Concurrent__task__loop__coll__graph.svg" width="163" height="119"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-types" name="pub-types"></a>
Public Types</h2></td></tr>
<tr class="memitem:aa164fb1fe1b3d7fce0de0174d77ea396"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">Thread_init_func</a> = <a class="el" href="classflow_1_1Function.html">Function</a>&lt; void(size_t thread_idx)&gt;</td></tr>
<tr class="memdesc:aa164fb1fe1b3d7fce0de0174d77ea396"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for the thread-initializer-function optional arg type to <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">More...</a><br /></td></tr>
<tr class="separator:aa164fb1fe1b3d7fce0de0174d77ea396"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-methods" name="pub-methods"></a>
Public Member Functions</h2></td></tr>
<tr class="memitem:a7b9123d43e1cfae899b0e1bb52bb6dde"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7b9123d43e1cfae899b0e1bb52bb6dde">~Concurrent_task_loop</a> () override</td></tr>
<tr class="memdesc:a7b9123d43e1cfae899b0e1bb52bb6dde"><td class="mdescLeft">&#160;</td><td class="mdescRight">Any implementing subclass's destructor shall execute <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> &ndash; see its doc header please &ndash; and then clean up any resources.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#a7b9123d43e1cfae899b0e1bb52bb6dde">More...</a><br /></td></tr>
<tr class="separator:a7b9123d43e1cfae899b0e1bb52bb6dde"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:afff5e62840791b309e178c5ddc26e594"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594">start</a> (<a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a> &amp;&amp;init_task_or_empty=<a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a>(), const <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">Thread_init_func</a> &amp;thread_init_func_or_empty=<a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">Thread_init_func</a>())=0</td></tr>
<tr class="memdesc:afff5e62840791b309e178c5ddc26e594"><td class="mdescLeft">&#160;</td><td class="mdescRight">Starts all threads in the thread pool; any queued <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>ed (and similar) tasks may begin executing immediately; and any future posted work may execute in these threads.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594">More...</a><br /></td></tr>
<tr class="separator:afff5e62840791b309e178c5ddc26e594"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:aadadb5b8b6c40ddc86c205de1b8f25b1"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1">stop</a> ()=0</td></tr>
<tr class="memdesc:aadadb5b8b6c40ddc86c205de1b8f25b1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such tasks from running; then gracefully stops/joins all threads in pool; and then returns.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1">More...</a><br /></td></tr>
<tr class="separator:aadadb5b8b6c40ddc86c205de1b8f25b1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a131335863b19446dbc349de181d4b5a1"><td class="memItemLeft" align="right" valign="top">virtual size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a131335863b19446dbc349de181d4b5a1">n_threads</a> () const =0</td></tr>
<tr class="memdesc:a131335863b19446dbc349de181d4b5a1"><td class="mdescLeft">&#160;</td><td class="mdescRight">How many threads does <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> start?  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#a131335863b19446dbc349de181d4b5a1">More...</a><br /></td></tr>
<tr class="separator:a131335863b19446dbc349de181d4b5a1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a4ee1c5f5785af0bcc6aed0757981ffe3"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3">create_op</a> ()=0</td></tr>
<tr class="memdesc:a4ee1c5f5785af0bcc6aed0757981ffe3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Return a new Op which can bundle together an arbitrary set of <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>s that would result in the provided task functions executing non-concurrently.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3">More...</a><br /></td></tr>
<tr class="separator:a4ee1c5f5785af0bcc6aed0757981ffe3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a54bd938b133103328a90d50823755358"><td class="memItemLeft" align="right" valign="top">virtual const <a class="el" href="classflow_1_1async_1_1Op__list.html">Op_list</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358">per_thread_ops</a> ()=0</td></tr>
<tr class="memdesc:a54bd938b133103328a90d50823755358"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns the optional-use, pre-created collection of per-thread <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> objects, such that the i-th <code>Op</code> therein corresponds to the i-th (of N, where N = # of threads in this pool) thread.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358">More...</a><br /></td></tr>
<tr class="separator:a54bd938b133103328a90d50823755358"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a24f96f97ee24bfabb06c8609bc0e94a6"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6">post</a> (<a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a> &amp;&amp;task, <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485">Synchronicity</a> synchronicity=<a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a4d7a5700444c0570af37b1f9bcc6eb1f">Synchronicity::S_ASYNC</a>)=0</td></tr>
<tr class="memdesc:a24f96f97ee24bfabb06c8609bc0e94a6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Cause the given <code>Task</code> (function) to execute within the thread pool as soon as possible, in the first thread available, in otherwise first-come-first-served fashion.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6">More...</a><br /></td></tr>
<tr class="separator:a24f96f97ee24bfabb06c8609bc0e94a6"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab0e31275441218c4d77df0730fd5e8f7"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ab0e31275441218c4d77df0730fd5e8f7">post</a> (const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;op, <a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a> &amp;&amp;task, <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485">Synchronicity</a> synchronicity=<a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a4d7a5700444c0570af37b1f9bcc6eb1f">Synchronicity::S_ASYNC</a>)=0</td></tr>
<tr class="memdesc:ab0e31275441218c4d77df0730fd5e8f7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Identical to the other <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> with the added constraint that no other <code>Task</code> <em>also</em> similarly posted with the equivalent <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> may execute concurrently.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#ab0e31275441218c4d77df0730fd5e8f7">More...</a><br /></td></tr>
<tr class="separator:ab0e31275441218c4d77df0730fd5e8f7"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ac6b98b440d52c079c22d7972c9b12e1b"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b">schedule_from_now</a> (const <a class="el" href="namespaceflow.html#a48799f1263cdeedec125be51a3db2b79">Fine_duration</a> &amp;from_now, <a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;task)=0</td></tr>
<tr class="memdesc:ac6b98b440d52c079c22d7972c9b12e1b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Equivalent to 2-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> but execution is scheduled for later, after the given time period passes.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b">More...</a><br /></td></tr>
<tr class="separator:ac6b98b440d52c079c22d7972c9b12e1b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ad0ca0710d990c15cb9ea31535bea24cc"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ad0ca0710d990c15cb9ea31535bea24cc">schedule_at</a> (const <a class="el" href="namespaceflow.html#a9d9cc2eeb10d398cff5591d446b763b8">Fine_time_pt</a> &amp;at, <a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;task)=0</td></tr>
<tr class="memdesc:ad0ca0710d990c15cb9ea31535bea24cc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Equivalent to 2-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> except one specifies an absolute time point instead of wait duration.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#ad0ca0710d990c15cb9ea31535bea24cc">More...</a><br /></td></tr>
<tr class="separator:ad0ca0710d990c15cb9ea31535bea24cc"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af3b04e2c7c2c8ee484a38b1156f8acc0"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#af3b04e2c7c2c8ee484a38b1156f8acc0">schedule_from_now</a> (const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;op, const <a class="el" href="namespaceflow.html#a48799f1263cdeedec125be51a3db2b79">Fine_duration</a> &amp;from_now, <a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;task)=0</td></tr>
<tr class="memdesc:af3b04e2c7c2c8ee484a38b1156f8acc0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Equivalent to 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> but execution is scheduled for later, after the given time period passes.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#af3b04e2c7c2c8ee484a38b1156f8acc0">More...</a><br /></td></tr>
<tr class="separator:af3b04e2c7c2c8ee484a38b1156f8acc0"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab1961159746ebe8b1787eadfbf728287"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ab1961159746ebe8b1787eadfbf728287">schedule_at</a> (const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;op, const <a class="el" href="namespaceflow.html#a9d9cc2eeb10d398cff5591d446b763b8">Fine_time_pt</a> &amp;at, <a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;task)=0</td></tr>
<tr class="memdesc:ab1961159746ebe8b1787eadfbf728287"><td class="mdescLeft">&#160;</td><td class="mdescRight">Equivalent to 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> except one specifies an absolute time point instead of wait duration.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#ab1961159746ebe8b1787eadfbf728287">More...</a><br /></td></tr>
<tr class="separator:ab1961159746ebe8b1787eadfbf728287"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ac446f6bfed9fb54d073a5f3f578ec4bb"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="namespaceflow_1_1async.html#a968806f54b14c697fd76b3339a2bdbbf">Task_engine_ptr</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb">task_engine</a> ()=0</td></tr>
<tr class="memdesc:ac446f6bfed9fb54d073a5f3f578ec4bb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a pointer to <em>an</em> internal <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> (a/k/a boost.asio <code>io_context</code>) for the purpose of performing a boost.asio <code>async_*()</code> action on some boost.asio I/O object in the immediate near future.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb">More...</a><br /></td></tr>
<tr class="separator:ac446f6bfed9fb54d073a5f3f578ec4bb"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="inherit_header pub_methods_classflow_1_1util_1_1Null__interface"><td colspan="2" onclick="javascript:toggleInherit('pub_methods_classflow_1_1util_1_1Null__interface')"><img src="closed.png" alt="-"/>&#160;Public Member Functions inherited from <a class="el" href="classflow_1_1util_1_1Null__interface.html">flow::util::Null_interface</a></td></tr>
<tr class="memitem:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="memItemLeft" align="right" valign="top">virtual&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Null__interface.html#a5916282577627e424a09884347eddbba">~Null_interface</a> ()=0</td></tr>
<tr class="memdesc:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="mdescLeft">&#160;</td><td class="mdescRight">Boring <code>virtual</code> destructor.  <a href="classflow_1_1util_1_1Null__interface.html#a5916282577627e424a09884347eddbba">More...</a><br /></td></tr>
<tr class="separator:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="related" name="related"></a>
Related Functions</h2></td></tr>
<tr><td class="ititle" colspan="2"><p >(Note that these are not member functions.) </p>
</td></tr>
<tr class="memitem:a7f2f976a53191a3b0cd28898bb23c551"><td class="memTemplParams" colspan="2">template&lt;typename Exec_ctx_ptr &gt; </td></tr>
<tr class="memitem:a7f2f976a53191a3b0cd28898bb23c551"><td class="memTemplItemLeft" align="right" valign="top">Exec_ctx_ptr&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551">op_to_exec_ctx</a> (<a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html">Concurrent_task_loop</a> *loop, const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;op)</td></tr>
<tr class="memdesc:a7f2f976a53191a3b0cd28898bb23c551"><td class="mdescLeft">&#160;</td><td class="mdescRight">Template specialization model for operation that obtains the underlying execution context, such as a <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> or <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>, stored in an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> generated by the given <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>.  <a href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551">More...</a><br /></td></tr>
<tr class="separator:a7f2f976a53191a3b0cd28898bb23c551"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><p >The core <a class="el" href="namespaceflow_1_1async.html" title="Flow module containing tools enabling multi-threaded event loops operating under the asynchronous-tas...">flow::async</a> interface, providing an optionally multi-threaded thread pool onto which runnable <code>Task</code>s, optionally arranged into concurrency-avoiding <code>Op</code>s, can be boost.asio-posted for subsequent execution. </p>
<h3>Thread safety</h3>
<p >All methods are thread-safe for read-write on a shared <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>, after its ctor returns, unless otherwise specified (but read on). This is highly significant, just as it is highly significant that boost.asio's <code>post(Task_engine&amp;)</code> is similarly thread-safe. However, it is <em>not</em> safe to call either <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> or <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> concurrently with itself or the other of the two, on the same <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>.</p>
<h3>First, select subclass to instantiate</h3>
<p >Whenever the user needs a pool of task-executing threads, meaning threads awaiting user-supplied work, to be <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>ed (etc.) in the boost.asio sense, they'll create a concrete subclass of this interface (the choice perhaps based on configuration, e.g.). The choice of subclass determines how tasks will be scheduled internally across threads, but the user need not worry about that after construction.</p>
<p >If your task loop is fundamentally single-threaded &ndash; which is <em>extremely</em> common and <em>typically</em> does <em>not</em> generalize to a multi-threaded one easily &ndash; then instead use the adapter <a class="el" href="classflow_1_1async_1_1Single__thread__task__loop.html" title="A Concurrent_task_loop-related adapter-style class that represents a single-thread task loop; essenti...">Single_thread_task_loop</a> which is <em>not</em> a part of <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> hierarchy but <em>does</em> use the relevant parts of it internally.</p>
<p >If you choose <a class="el" href="classflow_1_1async_1_1Single__thread__task__loop.html" title="A Concurrent_task_loop-related adapter-style class that represents a single-thread task loop; essenti...">Single_thread_task_loop</a> then it is not necessary to read further.</p>
<h3>Next, call <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a></h3>
<p >This starts the actual threads in the thread pool. Hence subsequent <code>post(F)</code> (etc.) will cause <code>F()</code> to be able to run in one of the threads. Some advanced points:</p><ul>
<li>You may <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> (etc.) before <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>. This will do no work but queue it up until <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>.</li>
<li>You may call <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> to synchronously, gracefully exit the threads. Any <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>ed (etc.) that hadn't yet run will remain queued. Any <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> (etc.) until the next <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> will (again) do no work and (again) remain queued until <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>.</li>
<li>If you save the (ref-counted) <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> from <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb" title="Returns a pointer to an internal util::Task_engine (a/k/a boost.asio io_context) for the purpose of p...">task_engine()</a> or from an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> via <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551" title="Template specialization model for operation that obtains the underlying execution context,...">op_to_exec_ctx()</a>, you may use it even after <code>*this</code> is destroyed. It is then your responsibility to start thread(s) in which to actually execute its tasks. Any queued tasks on the <code>Task_engine</code> will remain queued until then.</li>
<li>(This start/stop/run/post paradigm may be familiar to boost.asio (particularly <code>boost::asio::io_context</code>) users.)</li>
</ul>
<h3>Next, <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> tasks on it: <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a> to group task into operations</h3>
<p >One can <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> a task (in the same way one would simply <code>post(Task_engine&amp;)</code>). If one wants to execute an async op with 2+ non-concurrent tasks, they would pass the same <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> to <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> for each of the aforementioned 2+ <code>Task</code>s (which are simply <code>void</code> no-arg functions basically). An <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> can be created via <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a>; or if the task must be pinned to a specific pre-made per-software-thread <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a>, these are accessible via <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a>.</p>
<p >New applications should strive to use only <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a> and not touch the advanced-yet-legacy-ish <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a> facility. In a classic async-task-based-event-loop algorithm, it should be sufficient to execute <code>Task</code>s &ndash; sprinkling in <code>Op</code> tags when certain tasks together comprise multi-async-step ops &ndash; via one of the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> overloads. Hence simply make an <code>Op</code> via <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a> to associate <code>Task</code>s with each other, and that should be enough for most async algorithms.</p>
<p >Note also the optional <code>Synchronicity synchronicity</code> argument to the <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> methods. By default this acts like regular <code>post(Task_engine&amp;)</code>, but you can also access <code>dispatch(Task_engine&amp;)</code> type of behavior; you can wait for the task to complete using yet another mode. The latter feature, <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a57525f29ac96f4edd56c951e7d7c7b25" title="Same as Synchronicity::S_ASYNC but the posting routine then waits as long as necessary for the given ...">Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_COMPLETION</a>, may be particularly helpful at initialization time, such as if one needs to perform some startup tasks in the new thread(s) before continuing to general work on the loop. E.g., subclasses might, for convenience, wrap this ability in their constructors, so that the user can optionally provide an initializing task to run before the ctor returns.</p>
<p >Lastly <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485ae9a9ae292ea3fbbe3b313348dcec0846" title="Same as Synchronicity::S_ASYNC but the posting routine then waits as long as necessary for the given ...">Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_START</a> may be quite helpful in ensuring a certain task definitely does run &ndash; without waiting for it to actually run, but merely <em>begin</em> to run. More specifically <code>L.post(F, Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_START); L.stop();</code> will ensure <code>F()</code> will run at some point &ndash; but not wait for its completion. <code>L.post(F); L.stop();</code> will not ensure this at all; whether it does or not is a matter of luck. <code>L.post(F, Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_COMPLETION); L.stop();</code> <em>will</em> ensure it but also force a wait until <code>F()</code> finishes which may not be necessary and hence increases latency/responsiveness in the calling thread.</p>
<h3>And/or: Use <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a> to associate <code>Task</code>s with specific threads</h3>
<p >There are cases when the simple, conceptual approach just described (using <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a> only, if an <code>Op</code> is even desired at all) is not sufficient. Another approach is to pre-create N <code>Op</code>s, where N is the number of threads in the thread pool, and instead of <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a> one can randomly choose one of those N <code>Op</code>s and <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> onto that one (an <code>Op</code> is an <code>Op</code> regardless of how it was obtained). Informally, there are 2 known categories of use cases for this, with overlap:</p><ul>
<li>The legacy use case: Major daemons exist that were architected decades before <a class="el" href="namespaceflow_1_1async.html" title="Flow module containing tools enabling multi-threaded event loops operating under the asynchronous-tas...">flow::async</a> was even conceived, so they understandably achieve some of the same aims (to wit, non-concurrency of tasks in an op) by working with the lower-level/less abstract notion of a thread in a pool. Basically, if an <code>Op</code> corresponds to a worker thread specifically, then internally 2 <code>Task</code>s being assigned to that 1 <code>Op</code> would just mean executing them on that <code>Op</code>'s corresponding worker thread; threads are serial by definition, so the <code>Op</code> semantics are trivially satisfied. So to support such legacy designs, the per-thread-pre-created in <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a> allow user to obtain either a randomly chosen or a specifically indexed 1 of N per-thread <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a>.<ul>
<li>Example: Suppose a multi-threaded memory-caching server has a central data store and explicitly thread-local copies (periodically synchronized with the central one) thereof. With such a setup, it's a no-brainer to throw all work on a request that was originally assigned to thread 3 (random) of N <em>also</em> to per-thread Op #3 of N, for all <code>Task</code>s comprising that request's handling: Since all tasks operating in <code>Op</code> (therefore thread) #3 by definition execute non-concurrently, no locks are necessary when working with thread #3's thread-local object store copy. Simply, only thread <code>i</code> of N will ever touch object store <code>i</code> of N, to the extent it can be explicitly declared thread-local (<code>thread_local</code> in C++11, or similar).</li>
</ul>
</li>
<li>The thread-to-thread communication use case: This has come up in practice: If daemon 1 has N producer threads, and daemon 2 has N consumer threads, then one can set up N IPC queues, where thread <code>i</code> in either process accessing (writing and reading, respectively) only queue <code>i</code>. Then &ndash; assuming the queue itself is safe against 1 read occurring concurrently with 1 write &ndash; no further locking is required. Basically, thread <code>i</code> in daemon 1 deals with thread <code>i</code> in daemon 2, using a dedicated lock-free thread-<code>i</code>-access-only IPC queue.</li>
</ul>
<h3>Timers have similarly streamlined API: <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">schedule_task_from_now()</a></h3>
<p ><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> is absolutely core, of course. However obviously sometimes one needs to wait <em>asynchronously</em> for some kind of event and THEN execute a task on that event. In particular, executing it simply after some specific time period passes is common and has a dedicated API. This is called <em>scheduling a task</em> in our parlance.</p>
<p >If you want to schedule a task, first decide whether you need certain advanced capabilities. This is explained in the doc header for <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. If you decide you need advanced capabilities, then skip to the next subsection below, about general boost.asio I/O objects. Most of the time you won't, in which case read on:</p>
<p ><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> and <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ad0ca0710d990c15cb9ea31535bea24cc" title="Equivalent to 2-argument schedule_from_now() except one specifies an absolute time point instead of w...">schedule_at()</a> in this <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> interface provide all the capabilities of <code>util::schedule[d]_task*()</code> API. (Reminder: This includes canceling and short-firing the task with ease, more ease than if using the full on I/O <a class="el" href="namespaceflow_1_1util.html#ae7416d64d2989051104bb396e28e15e6" title="boost.asio timer.">util::Timer</a>, which is &ndash; again &ndash; explained below.) Just as with <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>, there is 1 version of each method for single tasks; and and 1 for operating within an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a>, meaning the timer completion handler.</p>
<h3>General boost.asio objects can be fully used with <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a></h3>
<p >Finally, there's general boost.asio "I/O object" work. An I/O object is usually a class &ndash; within boost.asio itself or a custom object &ndash; with 1 or more <em>asynchronous action</em> methods, always named in the style <code>async_*()</code>. To show how one would do this with <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>, let's do it in somewhat formal fashion:</p>
<p >Suppose you have boost.asio object X, for example <code>boost::asio::ip::tcp::socket</code> (in boost.asio itself) and <a class="el" href="classflow_1_1net__flow_1_1asio_1_1Peer__socket.html" title="A net_flow::Peer_socket that adds integration with boost.asio.">flow::net_flow::asio::Peer_socket</a> (a custom one), and we want to perform an <code>async_A()</code> action, which waits asynchronously for some event (e.g., a successful <code>tcp::socket::async_receive()</code> or <code><a class="el" href="classflow_1_1net__flow_1_1asio_1_1Peer__socket.html#a33adc635f29071b10ea59802405d9b6c" title="boost.asio-style asynchronous version that essentially performs non-nullptr_t net_flow::Peer_socket::...">net_flow::asio::Peer_socket::async_send()</a></code>, and then executes a <em>completion handler</em> task F:</p>
<div class="fragment"><div class="line"><a class="code hl_typedef" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4">flow::util::Task_engine</a> E; <span class="comment">// boost.asio user works directly with a Task_engine E running in 1+ threads.</span></div>
<div class="line">...</div>
<div class="line">X_type X(&amp;E);</div>
<div class="line"><span class="comment">// A_target represents 0 or more mutable data structures (e.g., received-data target buffer) that sync_A() would</span></div>
<div class="line"><span class="comment">//   modify in the background.</span></div>
<div class="line"><span class="comment">// A_settings represents 0 or more immutable/by-value args controlling behavior of the background sync_A() action.</span></div>
<div class="line">X.async_A(&amp;A_target, A_settings, F);</div>
<div class="line"><span class="comment">// Equivalent of X.sync_A(&amp;A_target, A_settings) is now executing in background via Task_engine E!</span></div>
<div class="line"><span class="comment">// Once done, it will act as if one called, from an unspecified thread: F(err_code, A_more_result_info).</span></div>
<div class="line"><span class="comment">//   - Error_code err_code is the success/failure result code.  In particular, `!err_code == true` on success.</span></div>
<div class="line"><span class="comment">//   - A_more_result_info represents 0 or more other bits of immutable/by-copy info indicating the results of</span></div>
<div class="line"><span class="comment">//     the background action.  For example, both `tcp::socket::async_receive()` and</span></div>
<div class="line"><span class="comment">//     `net_flow::Peer_socket::async_send()` will call `F(err_code, n)`, where `size_t n` is the # of bytes</span></div>
<div class="line"><span class="comment">//     received or sent respectively.</span></div>
<div class="ttc" id="anamespaceflow_1_1util_html_ac3e89a8a271b0ddc76ac2a0ce488dea4"><div class="ttname"><a href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4">flow::util::Task_engine</a></div><div class="ttdeci">boost::asio::io_context Task_engine</div><div class="ttdoc">Short-hand for boost.asio event service, the central class of boost.asio.</div><div class="ttdef"><b>Definition:</b> <a href="util__fwd_8hpp_source.html#l00135">util_fwd.hpp:135</a></div></div>
</div><!-- fragment --><p >That's the setup and should be familiar to boost.asio I/O object users. (Note that <a class="el" href="namespaceflow_1_1util.html#ae7416d64d2989051104bb396e28e15e6" title="boost.asio timer.">util::Timer</a> is a (relatively simple) I/O object itself; it lacks <code>A_settings</code> (one makes a call like <code>expires_at()</code> separately before the actual async action) and <code>A_more_result_info</code> (as <code>err_code</code> is sufficient) in particular. It also lacks any <code>A_target</code>. It's clearly the degenerate example of an I/O object action.) So how to write the above when working with a <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> instead of <code>Task_engine</code>?</p>
<div class="fragment"><div class="line"><a class="code hl_class" href="classflow_1_1async_1_1Concurrent__task__loop.html">flow::async::Concurrent_task_loop</a> L; <span class="comment">// Work with generalized thread pool L, not a Task_engine E.</span></div>
<div class="line">...</div>
<div class="line"><span class="comment">// ATTN!  A Task_engine is needed by boost.asio?  Use our API -- task_engine() -- to get one.</span></div>
<div class="line">X_type X(L.<a class="code hl_function" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb">task_engine</a>());</div>
<div class="line">X.async_A(&amp;A_target, A_settings, F);</div>
<div class="ttc" id="aclassflow_1_1async_1_1Concurrent__task__loop_html"><div class="ttname"><a href="classflow_1_1async_1_1Concurrent__task__loop.html">flow::async::Concurrent_task_loop</a></div><div class="ttdoc">The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...</div><div class="ttdef"><b>Definition:</b> <a href="concurrent__task__loop_8hpp_source.html#l00322">concurrent_task_loop.hpp:324</a></div></div>
<div class="ttc" id="aclassflow_1_1async_1_1Concurrent__task__loop_html_ac446f6bfed9fb54d073a5f3f578ec4bb"><div class="ttname"><a href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb">flow::async::Concurrent_task_loop::task_engine</a></div><div class="ttdeci">virtual Task_engine_ptr task_engine()=0</div><div class="ttdoc">Returns a pointer to an internal util::Task_engine (a/k/a boost.asio io_context) for the purpose of p...</div></div>
</div><!-- fragment --><p >Almost everything is the same! Just need to call that API to obtain a <code>Task_engine</code> to use. As a result:</p><ul>
<li>The background action, the equivalent of <code>X.sync_A()</code>, will be performed by some unspecified code in some unknown thread. We don't care how with boost.asio directly, and we don't care how with <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> either.</li>
<li>Then, for some <code>async_A()</code>s it will modify <code>A_target</code>. This, too, will be done by an unspecified thread <em>with no locking guarantees</em>. Hence, one must not access <code>A_target</code> from application threads. As wit boost.asio direct use, this is typical. For example no app code would access the target data buffer of a receive operation.</li>
<li>Finally, <code>F()</code> will be posted on completion via <code>Task_engine L.task_engine()</code>. Of course we guarantee it will be in some thread in the thread pool <code>L</code>.</li>
</ul>
<p >Finally, then, suppose the original snippet above is modified to use a <code>Strand</code>, to guarantee non-concurrency with some other boost.asio handler(s). This would look like:</p>
<div class="fragment"><div class="line"><a class="code hl_typedef" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4">flow::util::Task_engine</a> E;</div>
<div class="line"><a class="code hl_typedef" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e">flow::util::Strand</a> S(&amp;E); <span class="comment">// Create a Strand that guarantees non-concurrency of handlers posted onto Task_engine E.</span></div>
<div class="line">...</div>
<div class="line">X_type X(&amp;E);</div>
<div class="line">X.async_A(&amp;A_target, A_settings, boost::asio::bind_executor(S, F));</div>
<div class="line">...</div>
<div class="line">Y_type Y(&amp;E);</div>
<div class="line">Y.async_B(&amp;B_target, B_settings, boost::asio::bind_executor(S, G));</div>
<div class="line"><span class="comment">// X.sync_A() and Y.sync_B() are executing in background; F() and G() will run on respective completion;</span></div>
<div class="line"><span class="comment">// but F() and G() shall run non-concurrently by virtue of being wrapped by the same Strand: S.</span></div>
<div class="ttc" id="anamespaceflow_1_1util_html_aa59354ab408e978c8a7bda1a4706924e"><div class="ttname"><a href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e">flow::util::Strand</a></div><div class="ttdeci">Task_engine::strand Strand</div><div class="ttdoc">Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...</div><div class="ttdef"><b>Definition:</b> <a href="util__fwd_8hpp_source.html#l00138">util_fwd.hpp:138</a></div></div>
</div><!-- fragment --><p >To accomplish this with a <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> L</code>:</p>
<div class="fragment"><div class="line"><a class="code hl_class" href="classflow_1_1async_1_1Concurrent__task__loop.html">flow::async::Concurrent_task_loop</a> L;</div>
<div class="line"><span class="keyword">auto</span> op J = L.<a class="code hl_function" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3">create_op</a>(); <span class="comment">// ATTN! The syntax is different from Strands but the idea is identical.</span></div>
<div class="line">...</div>
<div class="line">X_type X(L.<a class="code hl_function" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb">task_engine</a>());</div>
<div class="line"><span class="comment">// ATTN! The syntax is again somewhat different from bind_executor(S, F), but the idea is equivalent.</span></div>
<div class="line">X.async_A(&amp;A_target, A_settings, <a class="code hl_function" href="namespaceflow_1_1async.html#af90c1e763d49c3f3033a74871e897394">flow::async::asio_handler_via_op</a>(&amp;L, J, F));</div>
<div class="line">...</div>
<div class="line">Y_type Y(L.<a class="code hl_function" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb">task_engine</a>());</div>
<div class="line">Y.async_B(&amp;B_target, B_settings, <a class="code hl_function" href="namespaceflow_1_1async.html#af90c1e763d49c3f3033a74871e897394">flow::async::asio_handler_via_op</a>(&amp;L, J, G));</div>
<div class="line"><span class="comment">// X.sync_A() and Y.sync_B() are executing in background; F and G will run on respective completion;</span></div>
<div class="line"><span class="comment">// but F() and G() shall run non-concurrently by virtue of being wrapped by the same Op: J.</span></div>
<div class="ttc" id="aclassflow_1_1async_1_1Concurrent__task__loop_html_a4ee1c5f5785af0bcc6aed0757981ffe3"><div class="ttname"><a href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3">flow::async::Concurrent_task_loop::create_op</a></div><div class="ttdeci">virtual Op create_op()=0</div><div class="ttdoc">Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...</div></div>
<div class="ttc" id="anamespaceflow_1_1async_html_af90c1e763d49c3f3033a74871e897394"><div class="ttname"><a href="namespaceflow_1_1async.html#af90c1e763d49c3f3033a74871e897394">flow::async::asio_handler_via_op</a></div><div class="ttdeci">auto asio_handler_via_op(Concurrent_task_loop *loop, const Op &amp;op, Handler &amp;&amp;handler)</div><div class="ttdoc">Given a boost.asio completion handler handler for a boost.asio async_*() action on some boost....</div><div class="ttdef"><b>Definition:</b> <a href="concurrent__task__loop_8hpp_source.html#l00691">concurrent_task_loop.hpp:691</a></div></div>
</div><!-- fragment --><p >However, now that you're working with an I/O object directly, you must be careful. Memorizing a <code>Task_engine</code> at construction has different effects depending on which concrete subclass of <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> <code>L</code> is. <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html" title="Concrete Concurrent_task_loop that is able to efficiently schedule Tasks within a given Op to execute...">Cross_thread_task_loop</a> in particular will assign it to whichever thread is best. <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html" title="Concrete Concurrent_task_loop that uses the legacy pin-Tasks-within-1-Op-to-1-thread method of achiev...">Segregated_thread_task_loop</a> will keep using the same random-ish thread chosen when <code>L.task_engine()</code> is called. If you need particular behavior, you will need to strongly consider what to do: It is no longer totally generic behavior independent of the subclass, as it generally is when it comes to the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> and <code>schedule_*()</code> APIs.</p>
<p >Lastly, if you are going down that road (which may be fully necessary) then consider the free function template <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551" title="Template specialization model for operation that obtains the underlying execution context,...">op_to_exec_ctx()</a> which is specialized for each concrete <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>; it takes a loop and an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> as input; and returns a boost.asio "execution context" which can be passed &ndash; much like a <code>Task_engine</code> in the above example &ndash; to I/O object constructors. See the specializations &ndash; as of this writing near <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html" title="Concrete Concurrent_task_loop that is able to efficiently schedule Tasks within a given Op to execute...">Cross_thread_task_loop</a> (returns <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>) and <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html" title="Concrete Concurrent_task_loop that uses the legacy pin-Tasks-within-1-Op-to-1-thread method of achiev...">Segregated_thread_task_loop</a> (returns <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a>) at least. Choose between the above technique and <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551" title="Template specialization model for operation that obtains the underlying execution context,...">op_to_exec_ctx()</a> when working directly with a boost.asio-compatible I/O object.</p>
<p >I am self-conscious at the length and seeming complexity of this formal writeup but must emphasize: This is using the same patterns as boost.asio users use. It's just a matter of mapping them to <code><a class="el" href="namespaceflow_1_1async.html" title="Flow module containing tools enabling multi-threaded event loops operating under the asynchronous-tas...">flow::async</a></code> Flow module's generalized <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> and <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> APIs. Reminder: The benefit of this is that one uses boost.asio-equivalent semantics; yet the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> concrete subclass can implement it internally in various ways that are or <em>aren't</em> what a direct use of <code>Task_engine</code> would do. However, when using I/O objects &ndash; as opposed to <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> &ndash; the genericness will be less generic. That is sometimes necessary.</p>
<p >TL;DR: Any boost.asio-style (whether from boost.asio itself or custom) I/O object is to be used as normal, but: To get a <code>Task_engine</code>, use <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb" title="Returns a pointer to an internal util::Task_engine (a/k/a boost.asio io_context) for the purpose of p...">task_engine()</a>. To get a <code>Strand</code>-like thing util::Op, use <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a>. To <em>use</em> the <code>Strand</code>-like thing util::Op, use <a class="el" href="namespaceflow_1_1async.html#af90c1e763d49c3f3033a74871e897394" title="Given a boost.asio completion handler handler for a boost.asio async_*() action on some boost....">asio_handler_via_op()</a>. Alternatively use actual <code>Task_engine</code>s or <code>Strand</code>s directly if necessary; see <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551" title="Template specialization model for operation that obtains the underlying execution context,...">op_to_exec_ctx()</a> specializations for that purpose. Lastly, make sure you understand the exact boost.asio behavior when using <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb" title="Returns a pointer to an internal util::Task_engine (a/k/a boost.asio io_context) for the purpose of p...">task_engine()</a> (yields <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a>), <a class="el" href="namespaceflow_1_1async.html#af90c1e763d49c3f3033a74871e897394" title="Given a boost.asio completion handler handler for a boost.asio async_*() action on some boost....">asio_handler_via_op()</a> (yields a <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>-bound callback), and/or <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a7f2f976a53191a3b0cd28898bb23c551" title="Template specialization model for operation that obtains the underlying execution context,...">op_to_exec_ctx()</a> (yields a <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a>, <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>, or something else depending on subclass, to be passed as an "execution context" to I/O object ctor).</p>
<h3>Are non-async boost.asio actions supported?</h3>
<p >boost.asio <code>async_*()</code> actions are supported by <code><a class="el" href="namespaceflow_1_1async.html" title="Flow module containing tools enabling multi-threaded event loops operating under the asynchronous-tas...">flow::async</a></code> module. What about synchronous and non-blocking operations? Well, sure, they're supported. This module is just not <em>about</em> them, hence the name. Just for perspective though:</p><ul>
<li>A non-blocking op (achieved in boost.asio normally by calling <code>something.non_blocking(true);</code> and then <code>some_op(something, ...)</code> or <code>something.some_op()</code>) can certainly be used whenever you want, in a task or outside of it, assuming of course you're not breaking thread-safety rules on concurrent access to <code>something</code>. The only "connection" to <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> is that the <code>something</code> may be associated with <code>*(this-&gt;<a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb" title="Returns a pointer to an internal util::Task_engine (a/k/a boost.asio io_context) for the purpose of p...">task_engine()</a>)</code>. That's fine.</li>
<li>A blocking op (achieved by calling <code>something.non_blocking(false);</code> and then same as in previous bullet) can also be used whenever. In some ways it's even less connected to <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>, as blocking ops are only tangentially related to <code>Task_engine</code> in the first place; they don't participate in the internal event loop and simply usually call some blocking OS API or similar. However, a blocking call does <em>block</em> the thread; so if you do this inside a <code>*this</code>-posted task, then that task will block.<ul>
<li>Informally: It it best not to mix blocking and non-blocking tasks in the same <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>. The blocking ones will harm the scheduler's ability to efficiently schedule the quick (non-blocking) tasks.</li>
<li>Informally: However, it is entirely reasonable and practical to limit a given <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> (even, or especially, a multi-thread one) to blocking tasks exclusively.<ul>
<li>One practical example is a multi-threaded DNS host resolver that maintains many threads performing blocking <code>getaddrinfo()</code> calls, since an async DNS API is not available; and a separate async-only loop/thread kicking off result-emitting handlers to the user, with the former blocking-only loop posting result-emitting tasks onto the async-only loop/thread. (boost.asio's out-of-the-box <code>resolver</code> provides an async API but is internally single-threaded and therefore unsuitable at scale.)</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>Design discussion re. <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> hierarchy</h3>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classflow_1_1async_1_1Task__qing__thread.html" title="Internally used building block of various concrete Concurrent_task_loop subclasses that encapsulates ...">Task_qing_thread</a>, particularly the constructor <a class="el" href="classflow_1_1async_1_1Task__qing__thread.html#abb03d1b5f50a2b6148da27139a2391da" title="Constructs object, immediately spawning new (worker) thread, memorizing a ref-counted reference to th...">Task_qing_thread::Task_qing_thread()</a> doc header, explaining how the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> hierarchy is an encapsulation of <code>vector&lt;<a class="el" href="classflow_1_1async_1_1Task__qing__thread.html" title="Internally used building block of various concrete Concurrent_task_loop subclasses that encapsulates ...">Task_qing_thread</a>&gt;</code>, arranged in various potential ways of working with each other. It also includes an intro to the question of how to choose <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html" title="Concrete Concurrent_task_loop that is able to efficiently schedule Tasks within a given Op to execute...">Cross_thread_task_loop</a> vs. <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html" title="Concrete Concurrent_task_loop that uses the legacy pin-Tasks-within-1-Op-to-1-thread method of achiev...">Segregated_thread_task_loop</a>, at a lower level.</dd></dl>
<p>While it is a clean interface, realistically speaking the entire existing hierarchy is perhaps best explained by immediately discussing the 2 concrete classes the API as of this writing. (More classes may well be added, but as of this writing and probably for posterity it makes sense to discuss these 2 specific ones.) The available pool types are:</p>
<ul>
<li><a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html" title="Concrete Concurrent_task_loop that is able to efficiently schedule Tasks within a given Op to execute...">Cross_thread_task_loop</a>: Internally, a single shared Task_engine and N <code><a class="el" href="classflow_1_1async_1_1Task__qing__thread.html" title="Internally used building block of various concrete Concurrent_task_loop subclasses that encapsulates ...">Task_qing_thread</a></code>s working together off that <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>-capable engine. N can be specified directly, or it can be auto-determined based on available hardware. The latter will also enable automatically pinning the threads in such a way as to attempt to minimize latency, namely avoiding hyper-threading or other physical core sharing by several hardware threads; this is done by making N = # of physical cores; and pinning each software thread to a distinct group of logical cores (hardware threads), so that each software thread gets its own physical core, avoiding latency-increasing "competition." An attempt is also made (achievable in Linux) to pin them in a consistent way, so that if another pool elsewhere uses the same code and config, they will arrange their same N threads in the same order. This can help if thread i from pool 1 is producer writing to some area in memory, while thread i from pool 2 is consumer of same, reading there. The <code>Cross_thread</code> part means that each multi-task sequence of callbacks constituting an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a>, s/t those callbacks must not execute concurrently, may use more than 1 thread (internally, via the boost.asio <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a> mechanism) which theoretically can improve use of thread time with asymmetrical load. It might also negate per-thread cache locality, etc., and counter-act the effectiveness of aforementioned pinning.<ul>
<li><code>Cross_thread</code> means cross-thread.</li>
</ul>
</li>
<li><a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html" title="Concrete Concurrent_task_loop that uses the legacy pin-Tasks-within-1-Op-to-1-thread method of achiev...">Segregated_thread_task_loop</a>: Internally, N <code><a class="el" href="classflow_1_1async_1_1Task__qing__thread.html" title="Internally used building block of various concrete Concurrent_task_loop subclasses that encapsulates ...">Task_qing_thread</a></code>s working together, each with its <em>own</em> <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>-capable Task_engine queue, meaning by contrast with <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html" title="Concrete Concurrent_task_loop that is able to efficiently schedule Tasks within a given Op to execute...">Cross_thread_task_loop</a> a given <code>Op</code> always executes its tasks on the same thread. Otherwise it works the same. Under asymmetrical load it might not use all available cross-thread time; however, it arguably also works straightforwardly "synergistically" with any attempts at per-processor-core pinning.</li>
</ul>
<p >The use is, of course, identical via the common API <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>.</p>
<p >Apologies for the conversational comment. The internal subtleties are encapsulated and hidden from user. Yet there is considerable flexibility available. One can think of this as a convenient wrapper around various functionality typically used manually and separately from each other &ndash; simplifying the core interface to just <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> and <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> and providing automatic flexibility as to what functionality is in fact used and when as a result. The functionality accessible: <code>post(Task_engine&amp;)</code>; scheduling via <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>; scheduling on specific thread; non-concurrency guarantees of 2+ tasks in one async op; and thread-count selection and pinning based on available processor architecture (hardware threads, physical cores). </p>

<p class="definition">Definition at line <a class="el" href="concurrent__task__loop_8hpp_source.html#l00322">322</a> of file <a class="el" href="concurrent__task__loop_8hpp_source.html">concurrent_task_loop.hpp</a>.</p>
</div><h2 class="groupheader">Member Typedef Documentation</h2>
<a id="aa164fb1fe1b3d7fce0de0174d77ea396" name="aa164fb1fe1b3d7fce0de0174d77ea396"></a>
<h2 class="memtitle"><span class="permalink"><a href="#aa164fb1fe1b3d7fce0de0174d77ea396">&#9670;&nbsp;</a></span>Thread_init_func</h2>

<div class="memitem">
<div class="memproto">
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">flow::async::Concurrent_task_loop::Thread_init_func</a> =  <a class="el" href="classflow_1_1Function.html">Function</a>&lt;void (size_t thread_idx)&gt;</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for the thread-initializer-function optional arg type to <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>. </p>

<p class="definition">Definition at line <a class="el" href="concurrent__task__loop_8hpp_source.html#l00329">329</a> of file <a class="el" href="concurrent__task__loop_8hpp_source.html">concurrent_task_loop.hpp</a>.</p>

</div>
</div>
<h2 class="groupheader">Constructor &amp; Destructor Documentation</h2>
<a id="a7b9123d43e1cfae899b0e1bb52bb6dde" name="a7b9123d43e1cfae899b0e1bb52bb6dde"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a7b9123d43e1cfae899b0e1bb52bb6dde">&#9670;&nbsp;</a></span>~Concurrent_task_loop()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">flow::async::Concurrent_task_loop::~Concurrent_task_loop </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">override</span><span class="mlabel">default</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Any implementing subclass's destructor shall execute <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> &ndash; see its doc header please &ndash; and then clean up any resources. </p>
<p >The behavior of <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> has subtle implications, so please be sure to understand what it does.</p>
<p >It is fine if <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> has already been called and returned. </p>

</div>
</div>
<h2 class="groupheader">Member Function Documentation</h2>
<a id="a4ee1c5f5785af0bcc6aed0757981ffe3" name="a4ee1c5f5785af0bcc6aed0757981ffe3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a4ee1c5f5785af0bcc6aed0757981ffe3">&#9670;&nbsp;</a></span>create_op()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> flow::async::Concurrent_task_loop::create_op </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Return a new Op which can bundle together an arbitrary set of <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>s that would result in the provided task functions executing non-concurrently. </p>
<p >That's informal; the formal semantics of what <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> means are in <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> doc header. Informally: please recall that a copy (of a copy, of a copy, ...) of an <code>Op</code> is an equivalent <code>Op</code>, and copying them is light-weight (at worst like copying <code>shared_ptr</code>).</p>
<p >All <code>Op</code>s shall remain valid throughout the lifetime of <code>*this</code>.</p>
<p >This is the more general method of obtaining an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a>, vs. going through <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a>. It should be used <em>unless</em> you specifically need to access some per-thread resource in the associated <code>Task</code>s. See class doc header for more discussion on this dichotomy. TL;DR: Use <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a> by default, <em>unless</em> the <code>Task</code>s you plan to execute are working on some per-thread resource.</p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a8257d8aa45ea527ce6c0783e37346743">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a8dd2594499859628be0ed997b5ca4643">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a8dd2594499859628be0ed997b5ca4643">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a8dd2594499859628be0ed997b5ca4643">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#a2c713a2692fd7eb17e4c6ebc22cc8cfc">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="a131335863b19446dbc349de181d4b5a1" name="a131335863b19446dbc349de181d4b5a1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a131335863b19446dbc349de181d4b5a1">&#9670;&nbsp;</a></span>n_threads()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual size_t flow::async::Concurrent_task_loop::n_threads </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td> const</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>How many threads does <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> start? </p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a28d7c70f0d3147ba48a10afa84ef98c1">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a2138f93d5fd11407973a7b7b13ca7353">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a2138f93d5fd11407973a7b7b13ca7353">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a2138f93d5fd11407973a7b7b13ca7353">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#a5c9a3da291fa961bb4d8c4be13c39bb8">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="a54bd938b133103328a90d50823755358" name="a54bd938b133103328a90d50823755358"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a54bd938b133103328a90d50823755358">&#9670;&nbsp;</a></span>per_thread_ops()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual const <a class="el" href="classflow_1_1async_1_1Op__list.html">Op_list</a> &amp; flow::async::Concurrent_task_loop::per_thread_ops </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Returns the optional-use, pre-created collection of per-thread <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> objects, such that the i-th <code>Op</code> therein corresponds to the i-th (of N, where N = # of threads in this pool) thread. </p>
<p >All <code>Op</code>s and this <code><a class="el" href="classflow_1_1async_1_1Op__list.html" title="Simple, immutable vector-like sequence of N opaque async::Op objects, usually corresponding to N work...">Op_list</a>&amp;</code> shall remain valid throughout the lifetime of <code>*this</code>.</p>
<p >This is an advanced/legacy-ish feature. Please see class doc header for discussion on when one should use this as opposed to the simpler <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a>.</p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a4c42c76a9d3f2926bb5545065d69783e">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a9c2676395574264b88a4c1f3b7b64b6e">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a9c2676395574264b88a4c1f3b7b64b6e">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a9c2676395574264b88a4c1f3b7b64b6e">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#af00698ef9a83bcc4e7e34fec89274569">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="ab0e31275441218c4d77df0730fd5e8f7" name="ab0e31275441218c4d77df0730fd5e8f7"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab0e31275441218c4d77df0730fd5e8f7">&#9670;&nbsp;</a></span>post() <span class="overload">[1/2]</span></h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual void flow::async::Concurrent_task_loop::post </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;&#160;</td>
          <td class="paramname"><em>op</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>task</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485">Synchronicity</a>&#160;</td>
          <td class="paramname"><em>synchronicity</em> = <code><a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a4d7a5700444c0570af37b1f9bcc6eb1f">Synchronicity::S_ASYNC</a></code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Identical to the other <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> with the added constraint that no other <code>Task</code> <em>also</em> similarly posted with the equivalent <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> may execute concurrently. </p>
<p >See doc header for <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> for a formal definition of what this call does w/r/t <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a>.</p>
<p >Reminder: This is thread-safe as explained in class doc header.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">op</td><td>The (presumably) multi-async-step operation to which <code>task</code> belongs, such that no <code>Task</code>s associated with <code>op</code> may execute concurrently with <code>task</code>. If <code>op.empty()</code> (a/k/a <code>op == <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">Op()</a></code>, recalling that <code><a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">Op()</a></code> is null/sentinel), then <code>assert()</code> trips. </td></tr>
    <tr><td class="paramname">task</td><td>See other <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>. </td></tr>
    <tr><td class="paramname">synchronicity</td><td>See other <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>. </td></tr>
  </table>
  </dd>
</dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a1b0703dffa2ea0a1105581e50cc17b9e">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a3ac438177671657e14f0fce378bce445">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a3ac438177671657e14f0fce378bce445">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a3ac438177671657e14f0fce378bce445">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#af64a0de5c3831cd89f8211e6abe1bba7">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="a24f96f97ee24bfabb06c8609bc0e94a6" name="a24f96f97ee24bfabb06c8609bc0e94a6"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a24f96f97ee24bfabb06c8609bc0e94a6">&#9670;&nbsp;</a></span>post() <span class="overload">[2/2]</span></h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual void flow::async::Concurrent_task_loop::post </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>task</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485">Synchronicity</a>&#160;</td>
          <td class="paramname"><em>synchronicity</em> = <code><a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a4d7a5700444c0570af37b1f9bcc6eb1f">Synchronicity::S_ASYNC</a></code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Cause the given <code>Task</code> (function) to execute within the thread pool as soon as possible, in the first thread available, in otherwise first-come-first-served fashion. </p>
<p ><code>task</code> may execute concurrently with some other <code>Task</code> if there are 2+ threads in <code>*this</code> pool. Meanings of "as soon as possible" and "available" are to be determined by the concrete method implementation. That is, the interface does not promise it'll use literally the first thread to be idle, but informally &ndash; all else being equal &ndash; that's a great goal.</p>
<p ><code>synchronicity</code> controls the precise behavior of the "post" operation. Read <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485" title="Enumeration indicating the manner in which asio_exec_ctx_post(), and various boost....">Synchronicity</a> <code>enum</code> docs carefully. That said: if left defaulted, <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> works in the <code>post(Task_engine&amp;)</code> manner: return immediately; then execute either concurrently in another thread or later in the same thread.</p>
<p >This is safe to call after <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a>, but <code>task()</code> will not run until <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> (see <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> doc header). <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a57525f29ac96f4edd56c951e7d7c7b25" title="Same as Synchronicity::S_ASYNC but the posting routine then waits as long as necessary for the given ...">Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_COMPLETION</a> and <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485ae9a9ae292ea3fbbe3b313348dcec0846" title="Same as Synchronicity::S_ASYNC but the posting routine then waits as long as necessary for the given ...">Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_START</a> modes will, therefore, block infinitely in that case; so don't do that after <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a>.</p>
<p >Reminder: This is thread-safe as explained in class doc header.</p>
<h3>Rationale note</h3>
<p >The callback arg would normally be the last arg, by Flow coding style. In this case it isn't, because it is more valuable to make <code>synchronicity</code> optional (which it can only be if it's the last arg).</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">task</td><td>Task to execute. <code>task</code> object itself may be <code>move</code>d and saved. </td></tr>
    <tr><td class="paramname">synchronicity</td><td>Controls when <code>task()</code> will execute particularly in relation to when this <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> call returns. </td></tr>
  </table>
  </dd>
</dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a9ae5be313170da86f361f8bf987b40b4">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#adb9a4a09e821aad135cfa1f493624630">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#adb9a4a09e821aad135cfa1f493624630">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#adb9a4a09e821aad135cfa1f493624630">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#ab785edcaa745fb859aaef4743478ea07">flow::async::Cross_thread_task_loop</a>.</p>

<p class="reference">Referenced by <a class="el" href="concurrent__task__loop_8hpp_source.html#l00691">flow::async::asio_handler_via_op()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1async_1_1Concurrent__task__loop_a24f96f97ee24bfabb06c8609bc0e94a6_icgraph.svg" width="374" height="47"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="ad0ca0710d990c15cb9ea31535bea24cc" name="ad0ca0710d990c15cb9ea31535bea24cc"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ad0ca0710d990c15cb9ea31535bea24cc">&#9670;&nbsp;</a></span>schedule_at() <span class="overload">[1/2]</span></h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a> flow::async::Concurrent_task_loop::schedule_at </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="namespaceflow.html#a9d9cc2eeb10d398cff5591d446b763b8">Fine_time_pt</a> &amp;&#160;</td>
          <td class="paramname"><em>at</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>task</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Equivalent to 2-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> except one specifies an absolute time point instead of wait duration. </p>
<dl class="section warning"><dt>Warning</dt><dd>See <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> warning.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">at</td><td>See <a class="el" href="namespaceflow_1_1util.html#aad8c8f7335eb892350dc386cb4be397e" title="Identical to schedule_task_from_now() except the time is specified in absolute terms.">util::schedule_task_at()</a>. </td></tr>
    <tr><td class="paramname">task</td><td>See <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a>. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#aec44a292a4f2800f40f67bfc4bf19367">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a2c3566acb42c14ce7fe31026a711a30b">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a2c3566acb42c14ce7fe31026a711a30b">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a2c3566acb42c14ce7fe31026a711a30b">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#aa8fb0ac1ac3dc4fb86b0a7dbec0a8686">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="ab1961159746ebe8b1787eadfbf728287" name="ab1961159746ebe8b1787eadfbf728287"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab1961159746ebe8b1787eadfbf728287">&#9670;&nbsp;</a></span>schedule_at() <span class="overload">[2/2]</span></h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a> flow::async::Concurrent_task_loop::schedule_at </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;&#160;</td>
          <td class="paramname"><em>op</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="namespaceflow.html#a9d9cc2eeb10d398cff5591d446b763b8">Fine_time_pt</a> &amp;&#160;</td>
          <td class="paramname"><em>at</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>task</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Equivalent to 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> except one specifies an absolute time point instead of wait duration. </p>
<dl class="section warning"><dt>Warning</dt><dd>See <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> warning.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">op</td><td>See 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>. </td></tr>
    <tr><td class="paramname">at</td><td>See <a class="el" href="namespaceflow_1_1util.html#aad8c8f7335eb892350dc386cb4be397e" title="Identical to schedule_task_from_now() except the time is specified in absolute terms.">util::schedule_task_at()</a>. </td></tr>
    <tr><td class="paramname">task</td><td>See <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a>. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a0d14e3b0251ca8e8f79f58d8fbc8aa9b">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a7d6b084d36b2bd119d73486be13fcf99">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a7d6b084d36b2bd119d73486be13fcf99">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a7d6b084d36b2bd119d73486be13fcf99">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#a3405f13bd63f6a9156cc6efb5c9f44be">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="ac6b98b440d52c079c22d7972c9b12e1b" name="ac6b98b440d52c079c22d7972c9b12e1b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ac6b98b440d52c079c22d7972c9b12e1b">&#9670;&nbsp;</a></span>schedule_from_now() <span class="overload">[1/2]</span></h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a> flow::async::Concurrent_task_loop::schedule_from_now </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="namespaceflow.html#a48799f1263cdeedec125be51a3db2b79">Fine_duration</a> &amp;&#160;</td>
          <td class="paramname"><em>from_now</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>task</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Equivalent to 2-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> but execution is scheduled for later, after the given time period passes. </p>
<p >The semantics are, in all ways in which this differs from 2-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>, those of <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. This includes the meaning of the returned value and the nature of <a class="el" href="namespaceflow_1_1util.html#aafa03984c5012ef7db2e7d01b6909a83" title="Short-hand for tasks that can be scheduled/fired by schedule_task_from_now() and similar.">util::Scheduled_task</a>. Also, in particular, one can perform actions like canceling, short-firing, and info-access by passing the returned handle into <a class="el" href="namespaceflow_1_1util.html#ad92e68a1b22556f2625292098c0036a2" title="Attempts to prevent the execution of a previously scheduled (by schedule_task_from_now() or similar) ...">util::scheduled_task_cancel()</a> and others.</p>
<dl class="section warning"><dt>Warning</dt><dd>If <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a131335863b19446dbc349de181d4b5a1" title="How many threads does start() start?">n_threads()</a> is 1, then you <em>must</em> not call any <code>util::scheduled_task_*()</code> function on the returned handle except from within <code>*this</code> loop's tasks.</dd></dl>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000005">Todo:</a></b></dt><dd>Deal with the scheduled-tasks-affected-from-outside-loop corner case of the <code>Concurrent_task_loop::schedule_*()</code> APIs. Perhaps add <code>bool in_loop_use_only</code> arg which, if <code>false</code>, will always disable the <code>single_threaded</code> optimization internally. At this time it always enables it if <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a131335863b19446dbc349de181d4b5a1" title="How many threads does start() start?">n_threads()</a> == 1</code> which will cause thread un-safety if the returned handle is touched from outside an in-loop task. <code>void</code> versions of the <code>schedule_*()</code> APIs should be added which would lack this, as in that case there is no handle to misuse outside the loop.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">from_now</td><td>See <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. </td></tr>
    <tr><td class="paramname">task</td><td>The task to execute within <code>*this</code> unless successfully canceled. <code>task</code> object itself may be <code>move</code>d and saved. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a4cb5a3192dad0ef7d5a228b18d11900a">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a79b1d2f2b5bf4fdf16e7701fe3bb44d1">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a79b1d2f2b5bf4fdf16e7701fe3bb44d1">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a79b1d2f2b5bf4fdf16e7701fe3bb44d1">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#a1008ae4c48d32ebf835d7a7ba203e5a9">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="af3b04e2c7c2c8ee484a38b1156f8acc0" name="af3b04e2c7c2c8ee484a38b1156f8acc0"></a>
<h2 class="memtitle"><span class="permalink"><a href="#af3b04e2c7c2c8ee484a38b1156f8acc0">&#9670;&nbsp;</a></span>schedule_from_now() <span class="overload">[2/2]</span></h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="namespaceflow_1_1util.html#aa0d10f5a906b3229f48979aa43e9ff7e">util::Scheduled_task_handle</a> flow::async::Concurrent_task_loop::schedule_from_now </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;&#160;</td>
          <td class="paramname"><em>op</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="namespaceflow.html#a48799f1263cdeedec125be51a3db2b79">Fine_duration</a> &amp;&#160;</td>
          <td class="paramname"><em>from_now</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af8c06052dd887bc77444550a7c243154">Scheduled_task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>task</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Equivalent to 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> but execution is scheduled for later, after the given time period passes. </p>
<p >The semantics are, in all ways in which this differs from 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>, those of <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. This includes the meaning of the returned value and the nature of <a class="el" href="namespaceflow_1_1util.html#aafa03984c5012ef7db2e7d01b6909a83" title="Short-hand for tasks that can be scheduled/fired by schedule_task_from_now() and similar.">util::Scheduled_task</a>.</p>
<dl class="section warning"><dt>Warning</dt><dd>See other <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac6b98b440d52c079c22d7972c9b12e1b" title="Equivalent to 2-argument post() but execution is scheduled for later, after the given time period pas...">schedule_from_now()</a> warning.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">op</td><td>See 3-argument <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a>. </td></tr>
    <tr><td class="paramname">from_now</td><td>See <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. </td></tr>
    <tr><td class="paramname">task</td><td>The task to execute within <code>*this</code>, subject to <code>op</code> constraints, unless successfully canceled. <code>task</code> object itself may be <code>move</code>d and saved. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="namespaceflow_1_1util.html#a74d4a66fb00055be4e1bd6ee98e04667" title="Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...">util::schedule_task_from_now()</a>. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a31bc0b91253d44f4ab6ee350b916d6f7">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ae0b5365734728eff8c995510a91b36be">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ae0b5365734728eff8c995510a91b36be">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ae0b5365734728eff8c995510a91b36be">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#a414e266ad227e12d47cb25f827251698">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="afff5e62840791b309e178c5ddc26e594" name="afff5e62840791b309e178c5ddc26e594"></a>
<h2 class="memtitle"><span class="permalink"><a href="#afff5e62840791b309e178c5ddc26e594">&#9670;&nbsp;</a></span>start()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual void flow::async::Concurrent_task_loop::start </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>init_task_or_empty</em> = <code><a class="el" href="namespaceflow_1_1async.html#af35fb65bdea1a3a92929ec2c4a6a6b72">Task</a>()</code>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">Thread_init_func</a> &amp;&#160;</td>
          <td class="paramname"><em>thread_init_func_or_empty</em> = <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aa164fb1fe1b3d7fce0de0174d77ea396">Thread_init_func</a>()</code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Starts all threads in the thread pool; any queued <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>ed (and similar) tasks may begin executing immediately; and any future posted work may execute in these threads. </p>
<p >Calling <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> after <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> is discouraged and may log a WARNING but is a harmless no-op. See also <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a>.</p>
<p >The optional <code>init_task_or_empty</code> arg is a convenience thing. It's equivalent to <code>post(init_task_or_empty, Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_COMPLETION)</code> executed upon return. <code>init_task_or_empty()</code> will run in the new thread pool; and only once it <code>return</code>s, <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> will <code>return</code>. Rationale: It has come up in our experience several times that one wants to execute something in the new thread(s) to initialize things, synchronously, before the main work &ndash; various async <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code>ing and other calls &ndash; can begin in earnest. Do note that any tasks enqueued before this <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> but after the last <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> or constructor may run first.</p>
<p >Suppose a user-supplied task posted onto a worker thread throws an uncaught exception. This will be handled the same as if that occurred directly in that thread; in other words we don't catch it in any way, not even to re-throw it or manually <code>std::abort()</code> or anything of that nature. We informally recommend you handle uncaught exceptions in a program-wide SIGABRT handler or equally program-wise custom <code>std::terminate()</code> (via <code>std::set_terminate()</code>). We informally recommend that all other threads similarly let any uncaught exception fall through and deal with the fallout at the global program-wide level (to avoid losing precious stack trace information).</p>
<p >Assuming no such uncaught exception is thrown, all threads will run until <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> or the destructor runs and returns.</p>
<h3>Thread safety</h3>
<p >As noted in the class doc header, all methods are thread-safe on a common <code>*this</code> unless noted otherwise. To wit: it is not safe to call <code>X.start()</code> concurrently with <code>X.start()</code> or with <code>X.stop()</code>.</p>
<h3>Thread initialization</h3>
<p >Each thread <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> starts shall be, soon, blocked by running an event loop (or part of a multi-thread event loop); meaning it will be either blocking waiting for posted tasks/active events or executing posted tasks/event handlers. It is, however, sometimes required to perform setup (usually of a low-level variety) in the thread before the event loop proper begins. (The use case that triggered this feature was wanting to execute Linux <code>setns(CLONE_NEWNET)</code> to affect the subsequent socket-create calls in that thread.) If needed: pass in a non-empty function as <code>thread_init_func_or_empty</code> arg; it will receive the thread index 0, 1, ... as the arg. It will run first-thing in the new thread. Subtlety: As of this writing "first-thing" means literally first-thing; it will run before any of the implementing <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>'s own code begins. (This may be relaxed in the future to merely "before the event loop is ready for tasks." Then this comment shall be updated.)</p>
<p >Note: <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> shall <em>block</em> until <em>all</em> <code>thread_init_func_or_empty()</code> invocations (if arg not <code>.empty()</code>) have completed. This can be important, for example, if the actions they are taking require elevated privileges, then this guarantee means one can drop privileges after that. Informally: we intuitively recommend against blocking in this callback, although perhaps some use case might require it. Just be careful.</p>
<h3>Design rationale (thread initialization arg)</h3>
<p >Consider the specific implementation of the present interface, <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html" title="Concrete Concurrent_task_loop that uses the legacy pin-Tasks-within-1-Op-to-1-thread method of achiev...">Segregated_thread_task_loop</a>. Something similar to this feature is possible without this <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> optional arg: One can simply <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a> onto each of the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a>, with <a class="el" href="namespaceflow_1_1async.html#a0a06794b16b72f2829ce3353557c8485a57525f29ac96f4edd56c951e7d7c7b25" title="Same as Synchronicity::S_ASYNC but the posting routine then waits as long as necessary for the given ...">Synchronicity::S_ASYNC_AND_AWAIT_CONCURRENT_COMPLETION</a>. It'll run as the first <em>task</em> in each thread, as opposed to strictly-speaking first-*thing*, but it's close enough. So why add this to the interface? Well, consider the other implementation, <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html" title="Concrete Concurrent_task_loop that is able to efficiently schedule Tasks within a given Op to execute...">Cross_thread_task_loop</a>. By definition it's not possible to target individual threads in that guy (<a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a54bd938b133103328a90d50823755358" title="Returns the optional-use, pre-created collection of per-thread async::Op objects, such that the i-th ...">per_thread_ops()</a> exists but its <code>Op</code>s are <em>per</em>-thread, not <em>in</em>-thread; they are <code>Strand</code>s, not threads). So then some other, Cross_thread_task_loop-*only* API would be necessary to get what we need. Hence it made sense to add this as an interface-level feature. Then these asymmetries go away naturally.</p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000003">Todo:</a></b></dt><dd><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">Concurrent_task_loop::start()</a> has an optional thread-initializer-function arg; it could be reasonable to ass a thread-finalizer-function arg symmetrically. As of this writing there is no use case, but it's certainly conceivable.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">init_task_or_empty</td><td>Ignored if <code>.empty()</code> (the default). Otherwise <code>init_task_or_empty()</code> shall execute in one of the threads started by this method, delaying the method's return to the caller until <code>init_task_or_empty()</code> returns in said spawned thread. </td></tr>
    <tr><td class="paramname">thread_init_func_or_empty</td><td>If not <code>.empty() == true</code>, <code>thread_init_func_or_empty(thread_idx)</code> shall be executed first-thing in each thread, for all <code>thread_idx</code> in [0, <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a131335863b19446dbc349de181d4b5a1" title="How many threads does start() start?">n_threads()</a>). <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> will return no sooner than when each such callback has finished. </td></tr>
  </table>
  </dd>
</dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a55fcb2e9f5410174c69cb1b9053a6ffd">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a6659220efe57750c9d8cd8e185d3299a">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a6659220efe57750c9d8cd8e185d3299a">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#a6659220efe57750c9d8cd8e185d3299a">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#a5705e34163dec8463a30361bdb2fa83f">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="aadadb5b8b6c40ddc86c205de1b8f25b1" name="aadadb5b8b6c40ddc86c205de1b8f25b1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#aadadb5b8b6c40ddc86c205de1b8f25b1">&#9670;&nbsp;</a></span>stop()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual void flow::async::Concurrent_task_loop::stop </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such tasks from running; then gracefully stops/joins all threads in pool; and then returns. </p>
<p >The post-condition is that the worker threads have fully and gracefully exited.</p>
<p >Upon return from this method, any further <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> or more complex async ops can safely be invoked &ndash; but they will not do any actual work, and no tasks or completion handlers will run until <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>. In particular <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#ac446f6bfed9fb54d073a5f3f578ec4bb" title="Returns a pointer to an internal util::Task_engine (a/k/a boost.asio io_context) for the purpose of p...">task_engine()</a> will still return a <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a>, and one can still invoke <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> and async I/O ops on it: doing so won't crash, but it won't do the requested work until <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>. (Recall that there are no more threads in which to do this work.) The destructor can then be invoked, at which point obviously one cannot <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a24f96f97ee24bfabb06c8609bc0e94a6" title="Cause the given Task (function) to execute within the thread pool as soon as possible,...">post()</a></code> (or anything else like it) either.</p>
<p >This condition is reversible via <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a>. In fact, <code>*this</code> starts in the stopped state, and <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> is required to make posted tasks actually execute.</p>
<p >Lastly, calling <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> after <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> returns is a harmless no-op. Also note the destructor shall call <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a>.</p>
<h3>Thread safety</h3>
<p >As noted in the class doc header, all methods are thread-safe on a common <code>*this</code> unless noted otherwise. To wit: it is not safe to call <code>X.stop()</code> concurrently with <code>X.stop()</code> or with <code>X.start()</code>.</p>
<p >You may call <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> from within a task/completion handler executing within <code>*this</code> thread pool. Of course you may also do this from another thread.</p>
<h3>Rationale</h3>
<p >This is similar to boost.asio <code>Task_engine::stop()</code>. At a minimum it is useful, when shutting down the app or module, in the situation where 2+ <code><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a></code>s routinely post work onto each other (or in at least 1 direction). To safely stop all 2+ loops, one would first invoke this <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> method on each <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>, in any order; having done that destroy (invoke dtor on) each <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>, also in any order. This way any cross-posting will safely work during the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> phase (but do nothing on the already-stopped loops); and by the time the destructor-invoking phase begins, no more cross-posting tasks can possibly be executing (as their threads don't even exist by then).</p>
<p >Note, however, that this is as graceful as we can generically guarantee &ndash; in that it won't crash/lead to undefined behavior on our account &ndash; but it is up to you to ensure your algorithm is robust, in that nothing bad will happen if tasks are suddenly prevented from running. For example, if task A locks some file, while task B later unlocks it, <em>you</em> are the one who must ensure you don't invoke <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> "between" task A and task B. (E.g., invoking it while A runs will let A complete; but it will very possibly prevent B from starting subsequently.) We have no way of knowing to let task B run first and only then stop the thread(s).</p>
<p >Lastly, the <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">stop()</a> and <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#afff5e62840791b309e178c5ddc26e594" title="Starts all threads in the thread pool; any queued post()ed (and similar) tasks may begin executing im...">start()</a> mechanism is amenable to dynamically configuring thread behavior such as the number of threads in the pool.</p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000004">Todo:</a></b></dt><dd>boost.asio has advanced features that might help to mark certain tasks as "must-run if already queued, even
if one `stop()`s"; consider providing user-friendly access to these features, perhaps in the context of the existing <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#aadadb5b8b6c40ddc86c205de1b8f25b1" title="Waits for any ongoing task(s)/completion handler(s) to return; then prevents any further-queued such ...">Concurrent_task_loop::stop()</a> API. These features are documented as of this writing at least in the <code>io_context</code> doc page. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a8d007bcbedf76eb13d4e1a2df087a470">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ad0ee24a26236098dfd67b68da120ff69">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ad0ee24a26236098dfd67b68da120ff69">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ad0ee24a26236098dfd67b68da120ff69">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#aa0f53f269524b701b23237766f79df2d">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<a id="ac446f6bfed9fb54d073a5f3f578ec4bb" name="ac446f6bfed9fb54d073a5f3f578ec4bb"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ac446f6bfed9fb54d073a5f3f578ec4bb">&#9670;&nbsp;</a></span>task_engine()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="namespaceflow_1_1async.html#a968806f54b14c697fd76b3339a2bdbbf">Task_engine_ptr</a> flow::async::Concurrent_task_loop::task_engine </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Returns a pointer to <em>an</em> internal <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> (a/k/a boost.asio <code>io_context</code>) for the purpose of performing a boost.asio <code>async_*()</code> action on some boost.asio I/O object in the immediate near future. </p>
<p >The mechanics of using this are explained in <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> doc header. Using this in any other fashion may lead to undefined behavior, while <code>*this</code> exists.</p>
<dl class="section return"><dt>Returns</dt><dd>A mutable <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> to use soon. Informally, the sooner one calls the intended <code>async_*()</code> action on it, the more effective the internal load-balancing. Formally, it is <em>allowed</em> to use it as long as <code>*this</code> exists (pre-destructor) and even beyond that, though any use beyond that point would pass the reponsibility on providing thread(s) to <code>run()</code> in becomes the user's. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1async_1_1Segregated__thread__task__loop.html#a5723cb843a014e8b77fa401cb93f241a">flow::async::Segregated_thread_task_loop</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ab5864fb0f46b84d5783ad194796c25f5">flow::async::Timed_concurrent_task_loop_impl&lt; Time_accumulator &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ab5864fb0f46b84d5783ad194796c25f5">flow::async::Timed_concurrent_task_loop_impl&lt; std::atomic&lt; perf::duration_rep_t &gt; &gt;</a>, <a class="el" href="classflow_1_1async_1_1Timed__concurrent__task__loop__impl.html#ab5864fb0f46b84d5783ad194796c25f5">flow::async::Timed_concurrent_task_loop_impl&lt; perf::duration_rep_t &gt;</a>, and <a class="el" href="classflow_1_1async_1_1Cross__thread__task__loop.html#ac46c461e0e5f4cf22305eb640ac2bbb0">flow::async::Cross_thread_task_loop</a>.</p>

</div>
</div>
<h2 class="groupheader">Friends And Related Function Documentation</h2>
<a id="a7f2f976a53191a3b0cd28898bb23c551" name="a7f2f976a53191a3b0cd28898bb23c551"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a7f2f976a53191a3b0cd28898bb23c551">&#9670;&nbsp;</a></span>op_to_exec_ctx()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Exec_ctx_ptr &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">Exec_ctx_ptr op_to_exec_ctx </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html">Concurrent_task_loop</a> *&#160;</td>
          <td class="paramname"><em>loop</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949">Op</a> &amp;&#160;</td>
          <td class="paramname"><em>op</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">related</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Template specialization model for operation that obtains the underlying execution context, such as a <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> or <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>, stored in an <a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> generated by the given <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a>. </p>
<p >Each subclass (impl) of <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> shall provide a specialization of this template with <code>Exec_ctx_ptr</code> template param being the appropriate boost.asio-compatible execution context type for that loop type's <code>Op <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html#a4ee1c5f5785af0bcc6aed0757981ffe3" title="Return a new Op which can bundle together an arbitrary set of post()s that would result in the provid...">create_op()</a></code>.</p>
<p >The mechanics of using this are explained in <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> doc header. Beyond that please see the particular specialization's doc header.</p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">Exec_ctx_ptr</td><td>A pointer type (raw or smart) pointing to an execution context type satisfying boost.asio's "execution context" concept. As of this writing the known values would be pointers to <a class="el" href="namespaceflow_1_1util.html#ac3e89a8a271b0ddc76ac2a0ce488dea4" title="Short-hand for boost.asio event service, the central class of boost.asio.">util::Task_engine</a> and <a class="el" href="namespaceflow_1_1util.html#aa59354ab408e978c8a7bda1a4706924e" title="Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...">util::Strand</a>, but really it depends on the particular subclass of <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> for the <code>*loop</code> arg. See its doc header near the particular <a class="el" href="classflow_1_1async_1_1Concurrent__task__loop.html" title="The core flow::async interface, providing an optionally multi-threaded thread pool onto which runnabl...">Concurrent_task_loop</a> subclass. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">loop</td><td>Loop object that, one way or another, generated and returned <code>op</code>. </td></tr>
    <tr><td class="paramname">op</td><td><a class="el" href="namespaceflow_1_1async.html#a024042c64b7dc544a7a5587afa4b1949" title="An object of this opaque type represents a collection of 1 or more async::Task, past or future,...">async::Op</a> from <code>*loop</code> from which to extract the execution context object on which you'd like to perform custom boost.asio work. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Pointer to a mutable execution context object. </dd></dl>

</div>
</div>
<hr/>The documentation for this class was generated from the following files:<ul>
<li>async/<a class="el" href="concurrent__task__loop_8hpp_source.html">concurrent_task_loop.hpp</a></li>
<li>async/<a class="el" href="async__fwd_8hpp_source.html">async_fwd.hpp</a></li>
<li>async/<a class="el" href="concurrent__task__loop_8cpp_source.html">concurrent_task_loop.cpp</a></li>
</ul>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Mar 28 2025 22:55:35 for Flow by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
